home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / print / gs261sr1.zip / GDEVSVGA.C < prev    next >
C/C++ Source or Header  |  1993-05-19  |  22KB  |  738 lines

  1. /* Copyright (C) 1991, 1992 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gdevsvga.c */
  20. /* SuperVGA display drivers for Ghostscript */
  21. #include "memory_.h"
  22. #include "gx.h"
  23. #include "gserrors.h"
  24. #include "gxdevice.h"
  25. #include "gdevpcfb.h"
  26. #include "gdevsvga.h"
  27.  
  28. /* The color map for dynamically assignable colors. */
  29. #define first_dc_index 64
  30. private int next_dc_index;
  31. #define dc_hash_size 293    /* prime, >num_dc */
  32. typedef struct { ushort rgb, index; } dc_entry;
  33. private dc_entry dynamic_colors[dc_hash_size + 1];
  34.  
  35. /* Macro for casting gx_device argument */
  36. #define fb_dev ((gx_device_svga *)dev)
  37.  
  38. /* Procedure records */
  39. #define svga_procs(open) {\
  40.     open, gx_default_get_initial_matrix,\
  41.     gx_default_sync_output, gx_default_output_page, svga_close,\
  42.     svga_map_rgb_color, svga_map_color_rgb,\
  43.     svga_fill_rectangle, gx_default_tile_rectangle,\
  44.     svga_copy_mono, svga_copy_color, gx_default_draw_line,\
  45.     svga_get_bits, gx_default_get_props, gx_default_put_props\
  46. }
  47.  
  48. /* Save the controller mode */
  49. private int svga_save_mode = -1;
  50.  
  51. /* ------ Internal routines ------ */
  52.  
  53. #define regen 0xa000
  54.  
  55. /* Construct a pointer for writing a pixel. */
  56. /* Assume 64K pages, 64K granularity. */
  57. /* We know that y is within bounds. */
  58. #define set_pixel_ptr(ptr, fbdev, x, y, wnum)\
  59. {    ulong index = (ulong)(y) * fbdev->raster + (uint)(x);\
  60.     if ( (uint)(index >> 16) != fbdev->page )\
  61.        {    (*fbdev->set_page)(fbdev, (fbdev->page = index >> 16), wnum);\
  62.        }\
  63.     ptr = (fb_ptr)MK_PTR(regen, (ushort)index);\
  64. }
  65. #define set_pixel_write_ptr(ptr, fbdev, x, y)\
  66.   set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_write)
  67. #define set_pixel_read_ptr(ptr, fbdev, x, y)\
  68.   set_pixel_ptr(ptr, fbdev, x, y, fbdev->wnum_read)
  69.  
  70. /* Find the graphics mode for a desired width and height. */
  71. /* Set the mode in the device structure and return 0, */
  72. /* or return an error code. */
  73. int
  74. svga_find_mode(gx_device *dev, const mode_info _ds *mip)
  75. {    for ( ; ; mip++ )
  76.     {    if ( mip->width >= fb_dev->width &&
  77.              mip->height >= fb_dev->height ||
  78.              mip[1].mode < 0
  79.            )
  80.         {    fb_dev->mode = mip;
  81.             gx_device_adjust_resolution(dev, mip->width, mip->height, 1);
  82.             fb_dev->raster = fb_dev->width;
  83.             return 0;
  84.         }
  85.     }
  86.     return_error(gs_error_rangecheck);
  87. }
  88.  
  89. /* Set the index for writing into the color DAC. */
  90. #define svga_dac_set_write_index(i) outportb(0x3c8, i)
  91.  
  92. /* Write 6-bit R,G,B values into the color DAC. */
  93. #define svga_dac_write(r, g, b)\
  94.   (outportb(0x3c9, r), outportb(0x3c9, g), outportb(0x3c9, b))
  95.  
  96. /* ------ Common procedures ------ */
  97.  
  98. /* Initialize the device structure and the DACs. */
  99. int
  100. svga_open(gx_device *dev)
  101. {    fb_dev->x_pixels_per_inch =
  102.       fb_dev->y_pixels_per_inch =
  103.         fb_dev->height / PAGE_HEIGHT_INCHES;
  104.     /* Set the display mode. */
  105.     if ( svga_save_mode < 0 )
  106.         svga_save_mode = (*fb_dev->get_mode)();
  107.     (*fb_dev->set_mode)(fb_dev->mode->mode);
  108.     /* Load the color DAC. */
  109.     svga_dac_set_write_index(0);
  110.        {    int c;
  111.         for ( c = 0; c < 64; c++ )
  112.            {    static const byte c2[10] =
  113.                { 0, 42, 0, 0, 0, 0, 0, 0, 21, 63 };
  114.             svga_dac_write(c2[(c >> 2) & 9], c2[(c >> 1) & 9],
  115.                        c2[c & 9]);
  116.            }
  117.        }
  118.     /* Initialize the dynamic color table. */
  119.     memset(dynamic_colors, 0, (dc_hash_size + 1) * sizeof(dc_entry));
  120.     next_dc_index = first_dc_index;
  121.     fb_dev->page = -1;
  122.     return 0;
  123. }
  124.  
  125. /* Close the device; reinitialize the display for text mode. */
  126. int
  127. svga_close(gx_device *dev)
  128. {    if ( svga_save_mode >= 0 )
  129.         (*fb_dev->set_mode)(svga_save_mode);
  130.     svga_save_mode = -1;
  131.     return 0;
  132. }
  133.  
  134. /* Map a r-g-b color to a palette index. */
  135. /* The first 64 entries of the color map are set */
  136. /* for compatibility with the older display modes: */
  137. /* these are indexed as 0.0.R0.G0.B0.R1.G1.B1. */
  138. gx_color_index
  139. svga_map_rgb_color(gx_device *dev, ushort r, ushort g, ushort b)
  140. {
  141. #define cv_bits(v,n) (v >> (gx_color_value_bits - n))
  142.     ushort r5 = cv_bits(r, 5), g5 = cv_bits(g, 5), b5 = cv_bits(b, 5);
  143.     static const byte cube_bits[32] =
  144.        {    0, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  145.         8, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  146.         1, 128, 128, 128, 128, 128, 128, 128, 128, 128,
  147.         9
  148.        };
  149.     uint cx = ((uint)cube_bits[r5] << 2) + ((uint)cube_bits[g5] << 1) +
  150.           (uint)cube_bits[b5];
  151.     ushort rgb;
  152.     register dc_entry _ds *pdc;
  153.     /* Check for a color on the cube. */
  154.     if ( cx < 64 ) return (gx_color_index)cx;
  155.     /* Not on the cube, check the dynamic color table. */
  156.     rgb = (r5 << 10) + (g5 << 5) + b5;
  157.     for ( pdc = &dynamic_colors[rgb % dc_hash_size]; pdc->rgb != 0; pdc++ )
  158.     {    if ( pdc->rgb == rgb )
  159.             return (gx_color_index)(pdc->index);
  160.     }
  161.     if ( pdc == &dynamic_colors[dc_hash_size] )
  162.     {    /* Wraparound */
  163.         for ( pdc = &dynamic_colors[0]; pdc->rgb != 0; pdc++ )
  164.         {    if ( pdc->rgb == rgb )
  165.                 return (gx_color_index)(pdc->index);
  166.         }
  167.     }
  168.     if ( next_dc_index == 256 )
  169.     {    /* No space left, report failure. */
  170.         return gx_no_color_index;
  171.     }
  172.     /* Not on the cube, and not in the dynamic table. */
  173.     /* Put in the dynamic table if space available. */
  174.     {    int i = next_dc_index++;
  175.         pdc->rgb = rgb;
  176.         pdc->index = i;
  177.         svga_dac_set_write_index(i);
  178.         svga_dac_write(cv_bits(r, 6), cv_bits(g, 6), cv_bits(b, 6));
  179.         return (gx_color_index)i;
  180.     }
  181. }
  182.  
  183. /* Map a color code to r-g-b. */
  184. /* This routine must invert the transformation of the one above. */
  185. /* Since this is practically never used, we just read the DAC. */
  186. int
  187. svga_map_color_rgb(gx_device *dev, gx_color_index color, ushort prgb[3])
  188. {    uint cval;
  189.     outportb(0x3c7, (byte)color);
  190. #define dacin() (cval = inportb(0x3c9) >> 1,\
  191.   ((cval << 11) + (cval << 6) + (cval << 1) + (cval >> 4)) >>\
  192.    (16 - gx_color_value_bits))
  193.     prgb[0] = dacin();
  194.     prgb[1] = dacin();
  195.     prgb[2] = dacin();
  196. #undef dacin
  197.     return 0;
  198. }
  199.  
  200. /* Copy a monochrome bitmap.  The colors are given explicitly. */
  201. /* Color = gx_no_color_index means transparent (no effect on the image). */
  202. int
  203. svga_copy_mono(gx_device *dev,
  204.   const byte *base, int sourcex, int sraster, gx_bitmap_id id,
  205.   int x, int y, int w, int h, gx_color_index czero, gx_color_index cone)
  206. {    uint raster = fb_dev->raster;
  207.     ushort limit;
  208.     register int wi;
  209.     uint skip;
  210.     int yi;
  211.     register fb_ptr ptr = (fb_ptr)0;
  212.     const byte *srow;
  213.     uint invert;
  214.     fit_copy(dev, base, sourcex, sraster, id, x, y, w, h);
  215.     limit = (ushort)-w;
  216.     skip = raster - w + 1;
  217.     srow = base + (sourcex >> 3);
  218. #define izero (int)czero
  219. #define ione (int)cone
  220.     if ( ione == no_color )
  221.     {    gx_color_index temp;
  222.         if ( izero == no_color ) return 0;    /* no-op */
  223.         temp = czero;
  224.         czero = cone;
  225.         cone = temp;
  226.         invert = ~0;
  227.     }
  228.     else
  229.         invert = 0;
  230.     /* Pre-filling saves us a test in the loop, */
  231.     /* and since tiling is uncommon, we come out ahead. */
  232.     if ( izero != no_color )
  233.         svga_fill_rectangle(dev, x, y, w, h, czero);
  234.     for ( yi = 0; yi < h; yi++ )
  235.        {    const byte *sptr = srow;
  236.         uint bits;
  237.         int bitno = sourcex & 7;
  238.         wi = w;
  239.         if ( PTR_OFF(ptr) <= skip )
  240.         {    set_pixel_write_ptr(ptr, fb_dev, x, y + yi);
  241.         }
  242.         else if ( PTR_OFF(ptr) > limit )
  243.         {    /* We're crossing a page boundary. */
  244.             /* This is extremely rare, so it doesn't matter */
  245.             /* how slow it is. */
  246.             int xi = (ushort)-PTR_OFF(ptr);
  247.             svga_copy_mono(dev, srow, sourcex & 7, sraster,
  248.                 gx_no_bitmap_id, x, y + yi, xi, 1,
  249.                 gx_no_col